<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Relations between Classes
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora140.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora142.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Relations between Classes</H2>
Classes can be related in two ways:
<OL type=1>
<LI>
 An aggregation relation, named Has-a:<BR>class <I>C</I><SUB><FONT SIZE=2>2</FONT></SUB> is related by Has-a with class <I>C</I><SUB><FONT SIZE=2>1</FONT></SUB> when <I>C</I><SUB><FONT SIZE=2>2</FONT></SUB> has
a field whose type is that of class <I>C</I><SUB><FONT SIZE=2>1</FONT></SUB>. This relation can be generalized as:
<I>C</I><SUB><FONT SIZE=2>2</FONT></SUB> has at least one field whose type is that of class <I>C</I><SUB><FONT SIZE=2>1</FONT></SUB>.

<LI> An inheritance relation, named Is-a:<BR>class <I>C</I><SUB><FONT SIZE=2>2</FONT></SUB> is a subclass of class <I>C</I><SUB><FONT SIZE=2>1</FONT></SUB> when <I>C</I><SUB><FONT SIZE=2>2</FONT></SUB>
extends the behavior of <I>C</I><SUB><FONT SIZE=2>1</FONT></SUB>. One big advantage of object-oriented
programming is the ability to extend the behavior of an existing class while
reusing the code written for the original class. When a class
is extended, the new class inherits all the fields (data and methods) of the
class being extended. </OL>
<A NAME="toc200"></A>
<H3> Aggregation</H3><A NAME="@concepts305"></A>
<A NAME="@concepts306"></A>
Class <I>C</I><SUB><FONT SIZE=2>1</FONT></SUB> aggregates class <I>C</I><SUB><FONT SIZE=2>2</FONT></SUB> when at least one
of its instance variables has type <I>C</I><SUB><FONT SIZE=2>2</FONT></SUB>. One gives the arity of the aggregation relation
when it is known.<BR>
<BR>

<H4> An Example of Aggregation</H4>
Let us define a figure as a set of points. Therefore we declare class
<I>picture</I> (see figure <A HREF="book-ora141.html#fig-rep-agregat">15.2</A>), in which one of the fields
is an array of points. Then the class <I>picture</I> aggregates
<I>point</I>, using the generalized relation Has-a.


<PRE><BR># <B>class</B><CODE> </CODE>picture<CODE> </CODE>n<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>ind<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>0</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>tab<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Array.create<CODE> </CODE>n<CODE> </CODE><TT>(</TT><B>new</B><CODE> </CODE>point<TT>(</TT><CODE>0</CODE><CODE>,</CODE><CODE>0</CODE><TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>add<CODE> </CODE>p<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>try</B><CODE> </CODE><CODE> </CODE>tab<CODE>.</CODE><TT>(</TT>ind<TT>)</TT><CODE>&lt;-</CODE>p<CODE> </CODE>;<CODE> </CODE>ind<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>ind<CODE> </CODE><CODE>+</CODE><CODE> </CODE><CODE>1</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>with</B><CODE> </CODE>Invalid_argument<TT>(</TT><CODE>"Array.set"</CODE><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>-&gt;<CODE> </CODE>failwith<CODE> </CODE><TT>(</TT><CODE>"picture.add:ind ="</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE><TT>(</TT>string_of_int<CODE> </CODE>ind<TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>remove<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>if</B><CODE> </CODE><TT>(</TT>ind<CODE> </CODE><CODE>&gt;</CODE><CODE> </CODE><CODE>0</CODE><TT>)</TT><CODE> </CODE><B>then</B><CODE> </CODE>ind<CODE> </CODE><CODE>&lt;-</CODE>ind<CODE>-</CODE><CODE>1</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>to_string<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>"["</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><B>for</B><CODE> </CODE>i<CODE>=</CODE><CODE>0</CODE><CODE> </CODE><B>to</B><CODE> </CODE>ind<CODE>-</CODE><CODE>1</CODE><CODE> </CODE><B>do</B><CODE> </CODE>s<CODE>:=</CODE><CODE> </CODE><CODE>!</CODE>s<CODE> </CODE><CODE>^</CODE><CODE> </CODE><CODE>" "</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE>tab<CODE>.</CODE><TT>(</TT>i<TT>)</TT>#to_string()<CODE> </CODE><B>done</B><CODE> </CODE>;<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE>!</CODE>s<TT>)</TT><CODE> </CODE><CODE>^</CODE><CODE> </CODE><CODE>"]"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class picture :</CODE><BR><CODE>  int -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    val mutable ind : int</CODE><BR><CODE>    val tab : point array</CODE><BR><CODE>    method add : point -&gt; unit</CODE><BR><CODE>    method remove : unit -&gt; unit</CODE><BR><CODE>    method to_string : unit -&gt; string</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
To build a figure, we create an instance of class <I>picture</I>, and insert
the points as required.


<PRE><BR># <B>let</B><CODE> </CODE>pic<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>picture<CODE> </CODE><CODE>8</CODE>;;<BR><CODE>val pic : picture = &lt;obj&gt;</CODE><BR># pic#add<CODE> </CODE>p1;<CODE> </CODE>pic#add<CODE> </CODE>p2;<CODE> </CODE>pic#add<CODE> </CODE>p3;;<BR><CODE>- : unit = ()</CODE><BR># pic#to_string<CODE> </CODE>();;<BR><CODE>- : string = "[ ( 0, 0) ( 3, 4) ( 3, 0)]"</CODE><BR>

</PRE>
<BR>
<BR>

<H4> A Graphical Notation for Aggregation</H4>
The relation between class <I>picture</I> and class <I>point</I> is
represented graphically in figure <A HREF="book-ora141.html#fig-rep-agregat">15.2</A>. An arrow with a
diamond at the tail represents aggregation.
In this example, class <I>picture</I> has 0 or more
points. 
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<DIV ALIGN=center>
<IMG SRC="book-ora059.gif">
</DIV>
<BR>
<DIV ALIGN=center>Figure 15.2: Aggregation relation.</DIV><BR>

<A NAME="fig-rep-agregat"></A>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>
Furthermore, we show above the arrow the arity of the relation.<BR>
<BR>
<A NAME="toc201"></A>
<H3> Inheritance Relation</H3><A NAME="@concepts307"></A>
<A NAME="@concepts308"></A>
<A NAME="@concepts309"></A>
This is the main relation in object-oriented programming. When class
<TT>c2</TT> inherits from class <TT>c1</TT>, it inherits all fields from the
parent class. It can also define new fields, or redefine inherited methods to
specialize them. Since the parent class has not been modified, the applications
using it do not need to be adapted to the changes introduced in the new class.<BR>
<BR>
The syntax of inheritance is as follows:


<H3> Syntax </H3> <HR>


<B>inherit</B> <I>name</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB> <I>p</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB> ...<I>p</I><SUB><I><FONT SIZE=2><I>n</I></FONT></I></SUB>
 [ <B>as</B> <I>name</I><SUB><I><FONT SIZE=2>2</FONT></I></SUB> ]



<HR>


Parameters <I>p</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB>, ..., <I>p</I><SUB><I><FONT SIZE=2><I>n</I></FONT></I></SUB> are what is expected from the
constructor of class <I>name</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB>. The optional keyword <B>as</B>
associates a name with
the parent class to provide access to its methods.
This feature is particularly useful when the child class
redefines a method of the parent class (see page <A HREF="book-ora142.html#sec-self-super">??</A>). <BR>
<BR>

<H4> An Example of Simple Inheritance</H4>
Using the classic example, we can extend class <I>point</I> by adding a color
attribute to the points. We define the class <I>colored_point</I>
inheriting from class <I>point</I>. The color is represented by the field
<TT>c</TT> of type <I>string</I>. We add a method <TT>get_color</TT> that
returns the value of the field. Finally, the string conversion method
is overridden to recognize the new attribute.


<H3> Note </H3> <HR>

The <TT>x</TT> and <TT>y</TT> variables seen in <TT>to_string</TT> are the fields,
not the class initialization arguments.


<HR>




<PRE><BR># <B>class</B><CODE> </CODE>colored_point<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>object</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>inherit</B><CODE> </CODE>point<CODE> </CODE><TT>(</TT>x<CODE>,</CODE>y<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE><B>mutable</B><CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE>c<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>get_color<CODE> </CODE><CODE>=</CODE><CODE> </CODE>c<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>set_color<CODE> </CODE>nc<CODE> </CODE><CODE>=</CODE><CODE> </CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>nc<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>method</B><CODE> </CODE>to_string<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>"( "</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE><TT>(</TT>string_of_int<CODE> </CODE>x<TT>)</TT><CODE> </CODE><CODE>^</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>", "</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE><TT>(</TT>string_of_int<CODE> </CODE>y<TT>)</TT><CODE> </CODE><CODE>^</CODE><CODE> </CODE><CODE>")"</CODE><CODE> </CODE><CODE>^</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>" ["</CODE><CODE> </CODE><CODE>^</CODE><CODE> </CODE>c<CODE> </CODE><CODE>^</CODE><CODE> </CODE><CODE>"] "</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>class colored_point :</CODE><BR><CODE>  int * int -&gt;</CODE><BR><CODE>  string -&gt;</CODE><BR><CODE>  object</CODE><BR><CODE>    val mutable c : string</CODE><BR><CODE>    val mutable x : int</CODE><BR><CODE>    val mutable y : int</CODE><BR><CODE>    method distance : unit -&gt; float</CODE><BR><CODE>    method get_color : string</CODE><BR><CODE>    method get_x : int</CODE><BR><CODE>    method get_y : int</CODE><BR><CODE>    method moveto : int * int -&gt; unit</CODE><BR><CODE>    method rmoveto : int * int -&gt; unit</CODE><BR><CODE>    method set_color : string -&gt; unit</CODE><BR><CODE>    method to_string : unit -&gt; string</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
The constructor arguments for <I>colored_point</I> are the pair of
coordinates required for the construction of a <I>point</I> and the color for
the colored point.<BR>
<BR>
The methods inherited, newly defined or redefined correspond to the
behaviors of instances of the class.


<PRE><BR># <B>let</B><CODE> </CODE>pc<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>new</B><CODE> </CODE>colored_point<CODE> </CODE><TT>(</TT><CODE>2</CODE><CODE>,</CODE><CODE>3</CODE><TT>)</TT><CODE> </CODE><CODE>"white"</CODE>;;<BR><CODE>val pc : colored_point = &lt;obj&gt;</CODE><BR># pc#get_color;;<BR><CODE>- : string = "white"</CODE><BR># pc#get_x;;<BR><CODE>- : int = 2</CODE><BR># pc#to_string();;<BR><CODE>- : string = "( 2, 3) [white] "</CODE><BR># pc#distance;;<BR><CODE>- : unit -&gt; float = &lt;fun&gt;</CODE><BR>

</PRE>

We say that the class <I>point</I> is a parent class of class
<I>colored_point</I> and that the latter is the child of the
former.<BR>
<BR>


<H3> Warning </H3> <HR>

When redefining a method in a child class, you must respect the method type
defined in the parent class.


<HR>

<BR>
<BR>

<H4> A Graphical Notation for Inheritance</H4>
The inheritance relation between classes is denoted by an arrow 
from the child class to the parent class. The head of the arrow is a closed triangle.
In the
graphical representation of inheritance, we only show the
new fields and methods, and redefined methods in the child class. Figure <A HREF="book-ora141.html#fig-rep-heritage">15.3</A>
displays the relation between class <I>colored_point</I> and its parent
<I>point</I>.<BR>
<BR>
<BLOCKQUOTE><DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV>
<DIV ALIGN=center>
<IMG SRC="book-ora060.gif">
<BR>
<BR>
<DIV ALIGN=center>Figure 15.3: Inheritance Relation.</DIV><BR>

<A NAME="fig-rep-heritage"></A>
</DIV>
<DIV ALIGN=center><HR WIDTH="80%" SIZE=2></DIV></BLOCKQUOTE>Since it contains additional methods, type <I>colored_point</I> differs from
type <I>point</I>. Testing for equality between instances of these classes
produces a long error message containing the whole type of
each class, in order to display the differences.


<PRE><BR># p1<CODE> </CODE><CODE>=</CODE><CODE> </CODE>pc;;<BR><CODE>Characters 6-8:</CODE><BR><CODE>This expression has type</CODE><BR><CODE>  colored_point =</CODE><BR><CODE>    &lt; distance : unit -&gt; float; get_color : string; get_x : int; get_y : </CODE><BR><CODE>      int; moveto : int * int -&gt; unit; rmoveto : int * int -&gt; unit;</CODE><BR><CODE>      set_color : string -&gt; unit; to_string : unit -&gt; string &gt;</CODE><BR><CODE>but is here used with type</CODE><BR><CODE>  point =</CODE><BR><CODE>    &lt; distance : unit -&gt; float; get_x : int; get_y : int;</CODE><BR><CODE>      moveto : int * int -&gt; unit; rmoveto : int * int -&gt; unit;</CODE><BR><CODE>      to_string : unit -&gt; string &gt;</CODE><BR><CODE>Only the first object type has a method get_color</CODE><BR>

</PRE>
<BR>
<BR>
<HR>
<A HREF="book-ora140.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora142.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
